using UnityEngine;
using System.Collections.Generic;
using UnityEngine.SceneManagement;

[CreateAssetMenu]//添加一个条目到Unity的菜单中
//工厂 用来创建形状
//自定义资产类型
public class ShapeFactory : ScriptableObject
{
    [SerializeField]
    Shape[] prefabs;//引入预制体

    [SerializeField]
    Material[] materials;//引入材质

    [SerializeField]
    bool recycle;//回收再利用

    List<Shape>[] pools;//对象池

    Scene poolScene;//场景池

    [SerializeField]
    int factoryId = int.MaxValue;

    public Shape Get(int shapeId = 0, int materialId = 0)
    {//创建并返回一个实例
        Shape instance;
        if(recycle)
        {
            if(pools == null)
                createPools();
            List<Shape> pool = pools[shapeId];
            int lastIndex = pool.Count - 1;
            if(lastIndex >= 0)
            {
                instance = pool[lastIndex];
                instance.gameObject.SetActive(true);
                pool.RemoveAt(lastIndex);
            }else{
                instance = Instantiate(prefabs[shapeId]);
                instance.OriginFactory = this;
                instance.ShapeId = shapeId;
                SceneManager.MoveGameObjectToScene(instance.gameObject,poolScene);//将对象迁移到场景池
            }
            
        }else{
            instance = Instantiate(prefabs[shapeId]);
            instance.ShapeId = shapeId;
        }
        instance.SetMaterial(materials[materialId], materialId);//设置材质
        return instance;
    }

    public Shape GetRandom()
    {//随机返回一个实例
        return Get(Random.Range(0, prefabs.Length), Random.Range(0, materials.Length));
    }

    void createPools()
    {//创建对象池
        //为什么使用列表而不是堆栈？
        //因为列表可以在播放模式下重新编译，而堆栈不能，Unity不会序列化堆栈

        pools = new List<Shape>[prefabs.Length];
        for(int i = 0;i<pools.Length;i++)
        {
            pools[i] = new List<Shape>();
        }
        if(Application.isEditor)
        {
            poolScene = SceneManager.GetSceneByName(name);
            if(poolScene.isLoaded)
            {
                GameObject[] rootObjects = poolScene.GetRootGameObjects();
                for(int i = 0;i<rootObjects.Length;i++)
                {
                    Shape pooledShape = rootObjects[i].GetComponent<Shape>();
                    if(!pooledShape.gameObject.activeSelf)
                    {
                        pools[pooledShape.ShapeId].Add(pooledShape);
                    }
                }
                return;
            }
        }
        
        poolScene = SceneManager.CreateScene(name);
    }

    public void Reclaim(Shape shapeToRecycle)
    {
        if(shapeToRecycle.OriginFactory != this)
        {
            Debug.LogError("Tried to reclaim shape with wrong factory.");
            return;
        }
        if(recycle)
        {
            if(pools == null)
            {
                createPools();
            }
            pools[shapeToRecycle.ShapeId].Add(shapeToRecycle);
            shapeToRecycle.gameObject.SetActive(false);
        }else{
            Destroy(shapeToRecycle.gameObject);//销毁所属的游戏对象来删除整个shape对象，而不仅仅是它的shape组件
        }
    }

    public int FactoryId
    {
        get{
            return factoryId;
        }
        set{
            if(factoryId == int.MinValue || factoryId == int.MaxValue)
            {
                factoryId = value;
            }else{
                Debug.Log("Not allowed to change factoryId." + factoryId);
            }
        }
    }
    

}